import Link from "next/link"; import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { EventRow } from "@/components/event-row"; import { LiveFeed } from "@/components/live-feed"; import { Badge, Bar, Chip, Empty, PageHeader, Panel, Score, Sparkline, Table, Td, TierBadge } from "@/components/ui"; import { api } from "@/lib/api"; import { CHANNELS, CHANNEL_KEYS, feedHref, fmtInt, typeLabel } from "@/lib/format"; export const dynamic = "force-dynamic"; /** Categories that are valid desks even when they have no recent event. */ const KNOWN = new Set([...CHANNEL_KEYS, "cloud", "developer", "consumer-tech", "semiconductors", "pharma", "statistics", "space", "automotive", "commerce", "payments", "crypto", "enterprise", "internet", "standards", "technology", "media", "politics", "sports", "energy", "transport", "telecom", "education", "retail", "gaming", "web-policy", "packages", "api"]); function channelOf(channel: string) { return CHANNELS.find((c) => c.key === channel && c.key !== "all" && c.key !== "breaking" && c.key !== "silent"); } export async function generateMetadata({ params }: { params: Promise<{ channel: string }> }): Promise { const { channel } = await params; const label = channelOf(channel)?.label ?? channel; return { title: `${label} desk`, description: `Live ${label} events detected by WebSensor: breaking, silent changes, active sources and trending entities.`, alternates: { canonical: `/category/${channel}` } }; } /** Specialized real-time desk (spec §103). */ export default async function CategoryPage({ params }: { params: Promise<{ channel: string }> }) { const { channel } = await params; if (!/^[a-z0-9-]{2,32}$/.test(channel)) notFound(); const desk = await api.categoryDesk(channel); if (!desk || (desk.recent.length === 0 && !KNOWN.has(channel))) notFound(); const chan = channelOf(channel); const label = chan?.label ?? channel; const series = desk.series.map((p) => p.n); const total48 = series.reduce((a, b) => a + b, 0); const maxType = Math.max(1, ...desk.by_type.map((t) => t.n)); const maxSrc = Math.max(1, ...desk.active_sources.map((s) => s.events_24h)); return ( <> Desk · {desk.categories.map((c) => ( {c} ))} } title={label} description={`Meaningful changes from sources categorized as ${desk.categories.map((c) => `“${c}”`).join(", ")} — official pages, feeds, status pages, documentation, filings.`} actions={
48 h
{fmtInt(total48)}
} />
); }